#region "Copyright (C) Lenny Granovsky. 2005-2013"
//This program is free software distribute under the terms of the GNU General Public License as published by
//the Free Software Foundation. Please read AssemblyInfo.cs file for more information.
#endregion

using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Collections.Specialized;
using System.Xml;
using System.Security.Cryptography;
using System.Web;

namespace Web.Enhancements.Rest
{
    [Serializable()]
    internal class WebRestSettings
	{
        public Dictionary<string, WebRestClassConfiguration> TypeMappings { get; private set; }
        public InfoCaching.ClassMethodInfoCacheLocation InfoCacheLocation { get; private set; }
        public List<string> AssureAssemblies { get; private set; }
        public bool IncludeExceptionDetailInErrors { get; private set; }
        public string RestFileExtension { get; set; }
        public ICustomJsonSerializerProvider CustomJsonSerializerProvider { get; set; }
        public bool AllowExploreMetadata { get; set; }

        public static WebRestSettings Current
        {
            get
            {
                return ((WebRestSettings)ConfigurationManager.GetSection("webRestServices"));
            }
        }

        public WebRestSettings(XmlElement XmlData)
		{
            this.RestFileExtension = "rest"; //default extension
            if (!string.IsNullOrWhiteSpace(XmlData.GetAttribute("restFileExtension")))
                this.RestFileExtension = XmlData.GetAttribute("restFileExtension").Trim();

            if (!string.IsNullOrWhiteSpace(XmlData.GetAttribute("allowExploreMetadata")))
            {
                bool allow = false;
                if (bool.TryParse(XmlData.GetAttribute("allowExploreMetadata").Trim(), out allow))
                    this.AllowExploreMetadata = allow;
            }

            if (XmlData.GetAttribute("cacheLocation") != null)
                this.InfoCacheLocation = (InfoCaching.ClassMethodInfoCacheLocation)Enum.Parse(typeof(InfoCaching.ClassMethodInfoCacheLocation), XmlData.GetAttribute("cacheLocation").Trim(), true);
            else
                this.InfoCacheLocation = InfoCaching.ClassMethodInfoCacheLocation.ApplicationVariable;

            this.IncludeExceptionDetailInErrors = true;
            if (XmlData.SelectSingleNode("serviceDebug") != null)
            {
                if (XmlData.SelectSingleNode("serviceDebug").Attributes.GetNamedItem("includeExceptionDetailInErrors") != null)
                    this.IncludeExceptionDetailInErrors = (XmlData.SelectSingleNode("serviceDebug").Attributes.GetNamedItem("includeExceptionDetailInErrors").Value.ToLower() == "true");
            }
            if (XmlData.SelectSingleNode("customJsonSerializerProvider") != null)
            {
                if (XmlData.SelectSingleNode("customJsonSerializerProvider").Attributes.GetNamedItem("type") != null)
                {
                    string tmpType = XmlData.SelectSingleNode("customJsonSerializerProvider").Attributes.GetNamedItem("type").Value;
                    Type dsrType = Type.GetType(tmpType, false);
                    if (dsrType != null)
                    {
                        object tmpDsr = Activator.CreateInstance(dsrType);
                        this.CustomJsonSerializerProvider = (ICustomJsonSerializerProvider)tmpDsr;
                    }
                }
            }

            this.AssureAssemblies = new List<string>();
            XmlNodeList oNodes = XmlData.SelectNodes("assureAssemblies/add");
            foreach(XmlNode node in oNodes)
                this.AssureAssemblies.Add(node.Attributes.GetNamedItem("assembly").Value.Trim());

            this.TypeMappings = new Dictionary<string, WebRestClassConfiguration>();
            oNodes = XmlData.SelectNodes("typeMapping/add");
            string type = "";
            string alias = "";
            foreach(XmlNode node in oNodes)
            {
                type = node.Attributes.GetNamedItem("type").Value.Trim();
                alias = node.Attributes.GetNamedItem("alias").Value.Trim();
                AddAliasMapping(alias, type, true);
            }

            //add alias for Web.Enhancements.Rest.WebRestExplorer
            Type webRestExplorerType = typeof(WebRestExplorer);
            AddAliasMapping(string.Format("base.{0}", webRestExplorerType.Name), webRestExplorerType.AssemblyQualifiedName, false);
            //add alias for Web.Enhancements.Rest.Help.HelpProvider
            Type webRestHelpType = typeof(Help.HelpProvider);
            AddAliasMapping(string.Format("base.help", webRestHelpType.Name), webRestHelpType.AssemblyQualifiedName, false);
            Type metaDataExplorerType = typeof(Help.MetadataExplorer);
            AddAliasMapping(string.Format("base.metadata", metaDataExplorerType.Name), metaDataExplorerType.AssemblyQualifiedName, false);
            //NOTE: add other classes from Web.Enhancements.Rest namespace as needed.
        }

        private void AddAliasMapping(string alias, string qualifiedTypeName, bool replaceDotWithPathSeparator)
        {
            string assemblyName = "";
            string fullName = TypeMapper.ExtractFullTypeName(qualifiedTypeName, out assemblyName);
            WebRestClassConfiguration classConfig = new WebRestClassConfiguration()
            {
                AliasName = alias,
                AssemblyName = assemblyName,
                FullName = fullName,
                FullQualifiedName = qualifiedTypeName,
                ReplaceDotWithPathSeparator = replaceDotWithPathSeparator
            };
            this.TypeMappings.Add(alias, classConfig);
        }
    }
}
